#include "palmvein.h"
#include "palmvein_com.h"
#include "palmvein_protocol.h"
#include "palmvein_encrypt.h"


#define PALMVEIN_OTA_TASK_LOG(format, ...) OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)
#define __PALMVEIN_OTA_TASK_LOG(format, ...) __OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)

#define VHW_UART_PALMVEIN           vUART_11

static uint8_t encryptionFlag = 0;		   //加密模式   0：不加密     1：加密
static s_msg_otaheader_data otaHeaderData;           //ota固件信息
static s_msg_startota_data otaStartData;             //ota启动信息
static s_msg_otapacket_data *ota_data = NULL;			//ota分包内容
static uint32_t palmvein_mtu = 0;                           //ota包最大传输长度
static uint32_t otaPackSum = 0;                         //ota包个数
static uint32_t otaCurrentPackPid = 0;                  //ota当前包
static uint8_t 	ota_ack_flag = 0;                        //ota包应答标志
static uint32_t ota_buffer_pos = 0;                     //ota缓存包位置
static uint32_t total_ota_len = 0;                      //ota包总大小
static uint32_t cur_ota_len = 0;                        //ota已完成长度





/**
  * @brief  掌静脉升级结果发送给主任务
  *
  * @note
  */
static void Palmvein_Ota_SendActionMsg(Palmvein_Result_enum_t result, uint8_t num)
{
	PalmVeinActionType_enum_t action = PALMVEIN_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
		case RESULT_SUCCESS_REPORT:
			action = PALMVEIN_ACTION_OTA_OK;
			break;
		case RESULT_FAIL_REPORT:
			action = PALMVEIN_ACTION_OTA_ERR;
			break; //OTA失败
		default:
			break;
	}
	if (PALMVEIN_ACTION_MAX != action)
	{
		PalmVeinMsg_t palmveinMsg;
		palmveinMsg.action = action;
		palmveinMsg.id = numbuf;
		OSAL_MessagePublish(&palmveinMsg, sizeof(palmveinMsg));
	}
}


/**
  * @brief  掌静脉ota分包发送
  *
  * @note
  */
ErrorStatus Palmvein_Ota_SendUpgradePack(uint8_t *data, uint16_t len)
{
    if (len == 0)
    {
        return ERROR;
    }

    if (ota_data == NULL)
    {
        ota_data = OSAL_Malloc(sizeof(s_msg_otapacket_data) + palmvein_mtu);
        if (ota_data == NULL)
        {
			PALMVEIN_OTA_TASK_LOG("ota_data = NULL");
            return ERROR;
        }
    }

    memcpy(&ota_data->data[ota_buffer_pos], data, len);
    ota_buffer_pos += len;
    cur_ota_len += len;
    if (ota_buffer_pos < palmvein_mtu && cur_ota_len < total_ota_len)
    {
        return SUCCESS;
    }

    // if(PalmveinCom_Get_TxStatus() != 0)
    // {
    //     uint32_t first_time = OSAL_GetTickCount();
    //     while (ota_ack_flag && ((OSAL_GetTickCount() - first_time) < 200))
    //     {
    //         PalmveinCom_RecvMsgProcess();
    //     }
    // }


    PALMVEIN_OTA_TASK_LOG("ota pid: %ld, len: %ld\r\n", otaCurrentPackPid, ota_buffer_pos);

    ota_data->psize = FACEOTA_SWAP16(ota_buffer_pos);
    ota_data->pid = FACEOTA_SWAP16(otaCurrentPackPid);

    ErrorStatus ret;
    
	ret = PalmveinCom_OTASendPacket(MID_OTA_PACKET, ota_data, ota_buffer_pos + sizeof(s_msg_otapacket_data), RESET);

    otaCurrentPackPid++;
    ota_ack_flag = 1;
    ota_buffer_pos = 0;

    return ret;
}

/**
  * @brief  掌静脉模组OTA完成后超时处理
  * @note
  */
void Palmvein_Ota_Timeout_process(void)
{
    OSAL_EventSingleCreate(COMP_PALMVEIN, EVENT_PALMVEIN_OTA_TIMEOUT, 60*1000, EVT_PRIORITY_MEDIUM);
}

/**
  * @brief  掌静脉OTA处理函数
  * @note
  */
void Palmvein_Ota_DealFun(Palmvein_DealParam_stu_t *param)
{
	PalmVeinMsg_t msg;
	Palmvein_DealParam_stu_t *parambuf = param;
	PalmVeinActionType_enum_t action = PALMVEIN_ACTION_MAX;

	switch (parambuf->event)
	{
			//启动升级
		case PALMVEIN_EVENT_START_OTA:
			Palmvein_P_Send_StartOta_CMD();
			break;

			//OTA已启动
		case PALMVEIN_EVENT_OTA_READY:
            PALMVEIN_OTA_TASK_LOG("PALMVEIN_EVENT_OTA_READY");
			//配置波特率
			Palmvein_P_Send_OtaCfgBaud_CMD(3);		//1: is 115200 (115200*1); 2 is 230400 (115200*2); 3 is 460800 (115200*4) ;4 1500000
            
			//TODO
			// Palmvein_P_Send_GetOtaStatus_CMD();		//获取ota状态
			break;

			//波特率配置完成
		case PALMVEIN_EVENT_OTA_CFG_BAUDRATE_FINISH: //波特率配置完成
            PALMVEIN_OTA_TASK_LOG("PALMVEIN_EVENT_OTA_CFG_BAUDRATE_FINISH");
            Device_SetUartBaudrate(VHW_UART_PALMVEIN,460800);
            OSAL_EventSingleCreate(COMP_PALMVEIN, EVENT_PALMVEIN_GET_STATUS, 200, EVT_PRIORITY_MEDIUM);
			break;

			//获取完成OTA状态
		case PALMVEIN_EVENT_OTA_STATUS_FINISH:
            PALMVEIN_OTA_TASK_LOG("PALMVEIN_EVENT_OTA_STATUS_FINISH");
            //上报ota准备好了
			msg.action = PALMVEIN_ACTION_OTA_READY;
			OSAL_MessagePublish(&msg,sizeof(msg));
			break;

			//固件信息发送完成
		case PALMVEIN_EVENT_OTA_FWINFO_FINISH:
			//上报ota准备好了
			msg.action = PALMVEIN_ACTION_OTA_READY;
			OSAL_MessagePublish(&msg,sizeof(msg));
			break;

            //分包完成
		case PALMVEIN_EVENT_OTA_PACKET:
            PALMVEIN_OTA_TASK_LOG("ota pack success\r\n");
			msg.action = PALMVEIN_ACTION_OTA_PACK_SUCCESS;
			OSAL_MessagePublish(&msg,sizeof(msg));

            if(otaCurrentPackPid == otaPackSum)
            {
                PALMVEIN_OTA_TASK_LOG("ota pack send finish\r\n");
                Palmvein_Ota_Timeout_process();
            }
			break;

			//OTA完成
		case PALMVEIN_EVENT_OTA_FINISH:
			PALMVEIN_OTA_TASK_LOG("ota finish %d\r\n",parambuf->result);
			Palmvein_Ota_SendActionMsg(parambuf->result,INVALID_NUM);
			break;

		default:
			break;

	}
}


void PalmveinOta_Start(uint8_t *data)
{
	uint32_t	file_len;
	uint32_t	pkt_num;
	uint16_t	pkt_size;
	uint8_t 	md5[32]; 

	memcpy(&pkt_size,&data[0],2);
	memcpy(&file_len,&data[2],4);
	memcpy(&md5,&data[6],32);



	ota_ack_flag = 0;
    cur_ota_len = 0;
    ota_buffer_pos = 0;
	otaCurrentPackPid = 0;
    total_ota_len = file_len;
    palmvein_mtu = pkt_size;
    
    PALMVEIN_OTA_TASK_LOG("pkt_size:%d, file_len:%d\r\n",pkt_size,file_len);
    PALMVEIN_OTA_TASK_LOG("md5:%s",md5);


    // raw data size of single packet 分包的大小，最大不超过4KBytes
    uint16_t num_pkt = ( file_len + pkt_size - 1 ) / pkt_size ;

    // 智能人脸模组OTA升级调试参考_20200426.pdf: 大端模式
    otaHeaderData.fsize_b[0] = file_len >> 24;
    otaHeaderData.fsize_b[1] = file_len >> 16;
    otaHeaderData.fsize_b[2] = file_len >> 8;
    otaHeaderData.fsize_b[3] = file_len >> 0;

    otaHeaderData.num_pkt[0] = num_pkt >> 24;
    otaHeaderData.num_pkt[1] = num_pkt >> 16;
    otaHeaderData.num_pkt[2] = num_pkt >> 8;
    otaHeaderData.num_pkt[3] = num_pkt >> 0;
    
    otaHeaderData.pkt_size[0] = pkt_size >> 8;
    otaHeaderData.pkt_size[1] = pkt_size >> 0;

    memcpy( otaHeaderData.md5_sum, md5, sizeof(otaHeaderData.md5_sum) );
    // MD5字符串必须小写
    for( uint32_t i=0; i<sizeof(otaHeaderData.md5_sum); i++ )
    {
        otaHeaderData.md5_sum[i] = tolower( otaHeaderData.md5_sum[i] );
    }  
    
    otaPackSum = otaHeaderData.num_pkt[0]*0x1000000 + otaHeaderData.num_pkt[1]*0x10000 + otaHeaderData.num_pkt[2]*0x100 + otaHeaderData.num_pkt[3];

    printf("ota pack sum :%d, ",otaPackSum);

    Palmvein_P_Send_OtaFwInfo_CMD(&otaHeaderData);	//发送固件信息

    if(PalmveinCom_Get_TxStatus() != 0)
    {
        uint32_t first_time = OSAL_GetTickCount();
        while (((OSAL_GetTickCount() - first_time) < 200))
        {
            PalmveinCom_RecvMsgProcess();
            if(PalmveinCom_Get_TxStatus() == 0)
            {
                break;
            }
        }
    }

}



ErrorStatus PalmveinOta_StartTest(void)
{
    //4B833C18B2B9B76C51459A88C1FD7335
    uint8_t test_md5[32] = "4b833c18b2b9b76c51459a88c1fd7335";          //

	ota_ack_flag = 0;
    cur_ota_len = 0;
    ota_buffer_pos = 0;
	otaCurrentPackPid = 0;
	total_ota_len = 0x666C0;
    palmvein_mtu = 128;
    
    //总包大小
    otaHeaderData.fsize_b[0] = 0;                   //
    otaHeaderData.fsize_b[1] = 0x06;                //0x666C0
    otaHeaderData.fsize_b[2] = 0x66;            
    otaHeaderData.fsize_b[3] = 0xC0;

    //分包数
    otaHeaderData.num_pkt[0] = 0x00;
    otaHeaderData.num_pkt[1] = 0x00;                //
    otaHeaderData.num_pkt[2] = 0x0c;                //820=0x0334  3278=0cce
    otaHeaderData.num_pkt[3] = 0xce;
    
    //分包大小
    otaHeaderData.pkt_size[0] = 0x00;			//512=0x200 128=0x80
    otaHeaderData.pkt_size[1] = 0x80;

    memcpy(&otaHeaderData.md5_sum,test_md5,32);


    otaPackSum = otaHeaderData.num_pkt[0]*0x1000000 + otaHeaderData.num_pkt[1]*0x10000 + otaHeaderData.num_pkt[2]*0x100 + otaHeaderData.num_pkt[3];
    PALMVEIN_OTA_TASK_LOG(" otaPackSum %x\r\n",otaPackSum);
    
    PALMVEIN_OTA_TASK_LOG("\r\nfsizeb:");
    for(int i=0;i<4;i++)
    {
        PALMVEIN_OTA_TASK_LOG("%02x",otaHeaderData.fsize_b[i]);
    }
    PALMVEIN_OTA_TASK_LOG("\n");

    PALMVEIN_OTA_TASK_LOG("test md5:%s",otaHeaderData.md5_sum);

	// Palmvein_P_Send_OtaFwInfo_CMD(&otaHeaderData);	//发送固件信息

    return SUCCESS;
}
